/**
 * @file pulse_data.h
 * @brief 脉冲数据模块 - 处理脉冲计数相关的所有数据类型
 * @details 本头文件定义了104协议中脉冲数据类型的结构体和操作函数，
 *          包括脉冲计数、脉冲数据组、脉冲配置等。
 *          支持完整的数据创建、转换和验证功能。
 * 
 * @author zyb
 * @date 2025-10-12
 * @version 1.0
 * 
 * @note 所有数据类型都遵循IEC 60870-5-104协议规范
 * @warning 脉冲数据涉及计量，需要严格验证
 * 
 * @see protocol_types.h
 * @see error_codes.h
 * @see validation_utils.h
 */

#ifndef PULSE_DATA_H
#define PULSE_DATA_H

#include "../../common/types/include/protocol_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/* ==================== 脉冲数据类型定义 ==================== */

/**
 * @brief 脉冲数据点配置
 */
typedef struct {
    u16 point_id;           /* 点号 */
    char name[64];          /* 名称 */
    float coefficient;      /* 系数 */
    float offset;           /* 偏移 */
} pulse_point_config_t;

/**
 * @brief 脉冲数据
 */
typedef struct {
    u16 point_id;           /* 点号 */
    u32 pulse_count;        /* 脉冲计数值 */
    float calculated_value; /* 计算后的值 (计数值 * 系数 + 偏移) */
    cp56time2a_t timestamp; /* 时间戳 */
} pulse_data_t;

/**
 * @brief 脉冲数据组
 */
typedef struct {
    pulse_data_t* data;     /* 脉冲数据数组 */
    u32 count;              /* 数据个数 */
    u32 max_count;          /* 最大数据个数 */
} pulse_data_group_t;


/* ==================== 脉冲数据转换函数 ==================== */

/**
 * @brief 脉冲数据点配置转换为字节数组
 * @details 将脉冲数据点配置结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化。
 * 
 * @param config 脉冲数据点配置结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据序列化
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_pulse_point_config
 * @see validate_pulse_point_config
 */
protocol_error_t pulse_point_config_to_bytes(const pulse_point_config_t* config,
                                            u8* buffer, u32 buffer_size, u32* actual_length);

/**
 * @brief 字节数组转换为脉冲数据点配置
 * @details 将104协议规定的字节数组格式转换为脉冲数据点配置结构。
 *          按照协议规范进行数据反序列化。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param config 脉冲数据点配置结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据反序列化
 * @warning 数据长度必须足够容纳脉冲数据点配置
 * 
 * @see pulse_point_config_to_bytes
 * @see validate_pulse_point_config
 */
protocol_error_t bytes_to_pulse_point_config(const u8* data, u32 length,
                                            pulse_point_config_t* config);

/**
 * @brief 遥脉数据转换为字节数组
 * @param data 遥脉数据结构
 * @param buffer 输出缓冲区
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度
 * @return 协议错误码
 */
protocol_error_t pulse_data_to_bytes(const pulse_data_t* data,
                                    u8* buffer, u32 buffer_size, u32* actual_length);

/**
 * @brief 字节数组转换为遥脉数据
 * @param data 字节数组
 * @param length 数据长度
 * @param pulse_data 遥脉数据结构输出
 * @return 协议错误码
 */
protocol_error_t bytes_to_pulse_data(const u8* data, u32 length,
                                    pulse_data_t* pulse_data);

/**
 * @brief 遥脉数据组转换为字节数组
 * @param group 遥脉数据组结构
 * @param buffer 输出缓冲区
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度
 * @return 协议错误码
 */
protocol_error_t pulse_data_group_to_bytes(const pulse_data_group_t* group,
                                          u8* buffer, u32 buffer_size, u32* actual_length);

/**
 * @brief 字节数组转换为遥脉数据组
 * @param data 字节数组
 * @param length 数据长度
 * @param group 遥脉数据组结构输出
 * @return 协议错误码
 */
protocol_error_t bytes_to_pulse_data_group(const u8* data, u32 length,
                                           pulse_data_group_t* group);

/* ==================== 验证函数 ==================== */

/**
 * @brief 验证脉冲数据点配置
 * @details 验证脉冲数据点配置结构的完整性和有效性。
 *          检查点号、名称、系数和偏移的有效性。
 * 
 * @param config 脉冲数据点配置结构，不能为NULL
 * @return 验证结果
 *         - 1: 脉冲数据点配置有效
 *         - 0: 脉冲数据点配置无效
 * 
 * @note 验证点号、名称、系数和偏移的有效性
 * @warning 输入指针不能为NULL
 * 
 * @see is_pulse_point_id_valid
 * @see is_pulse_coefficient_valid
 * @see pulse_point_config_t
 */
int validate_pulse_point_config(const pulse_point_config_t* config);

/**
 * @brief 验证脉冲数据
 * @details 验证脉冲数据结构的完整性和有效性。
 *          检查点号、计数值、计算值和时间戳的有效性。
 * 
 * @param pulse 脉冲数据结构，不能为NULL
 * @return 验证结果
 *         - 1: 脉冲数据有效
 *         - 0: 脉冲数据无效
 * 
 * @note 验证点号、计数值、计算值和时间戳的有效性
 * @warning 输入指针不能为NULL
 * 
 * @see is_pulse_point_id_valid
 * @see is_pulse_count_valid
 * @see is_cp56time2a_valid
 * @see pulse_data_t
 */
int validate_pulse_data(const pulse_data_t* pulse);

/**
 * @brief 验证脉冲数据组
 * @details 验证脉冲数据组结构的完整性和有效性。
 *          检查数据个数、数据数组和每个数据的有效性。
 * 
 * @param group 脉冲数据组结构，不能为NULL
 * @return 验证结果
 *         - 1: 脉冲数据组有效
 *         - 0: 脉冲数据组无效
 * 
 * @note 验证数据个数、数据数组和每个数据的有效性
 * @warning 输入指针不能为NULL
 * 
 * @see is_pulse_group_count_valid
 * @see validate_pulse_data
 * @see pulse_data_group_t
 */
int validate_pulse_data_group(const pulse_data_group_t* group);

/* ==================== 辅助函数 ==================== */

/**
 * @brief 获取脉冲数据点配置大小
 * @details 获取脉冲数据点配置结构在字节数组中的大小。
 *          用于缓冲区大小计算。
 * 
 * @return 脉冲数据点配置大小（字节）
 * 
 * @note 脉冲数据点配置大小：74字节（点号2字节 + 名称64字节 + 系数4字节 + 偏移4字节）
 * @warning 此函数是线程安全的
 * 
 * @see get_pulse_data_size
 * @see get_pulse_data_group_size
 * @see pulse_point_config_t
 */
u32 get_pulse_point_config_size(void);

/**
 * @brief 获取脉冲数据大小
 * @details 获取脉冲数据结构在字节数组中的大小。
 *          用于缓冲区大小计算。
 * 
 * @return 脉冲数据大小（字节）
 * 
 * @note 脉冲数据大小：17字节（点号2字节 + 计数值4字节 + 计算值4字节 + 时间戳7字节）
 * @warning 此函数是线程安全的
 * 
 * @see get_pulse_point_config_size
 * @see get_pulse_data_group_size
 * @see pulse_data_t
 */
u32 get_pulse_data_size(void);

/**
 * @brief 获取脉冲数据组大小
 * @details 获取脉冲数据组结构在字节数组中的大小。
 *          用于缓冲区大小计算。
 * 
 * @param count 数据个数
 * @return 脉冲数据组大小（字节）
 * 
 * @note 脉冲数据组大小：4字节 + (数据个数 * 17字节)
 * @warning 此函数是线程安全的
 * 
 * @see get_pulse_point_config_size
 * @see get_pulse_data_size
 * @see pulse_data_group_t
 */
u32 get_pulse_data_group_size(u32 count);

/**
 * @brief 计算脉冲数据值
 * @details 根据脉冲计数值、系数和偏移计算实际值。
 *          计算公式：实际值 = 计数值 * 系数 + 偏移
 * 
 * @param pulse_count 脉冲计数值
 * @param coefficient 系数
 * @param offset 偏移
 * @return 计算后的实际值
 * 
 * @note 计算公式：实际值 = 计数值 * 系数 + 偏移
 * @warning 系数和偏移必须为有效值
 * 
 * @see calculate_pulse_data_from_config
 * @see is_pulse_coefficient_valid
 */
float calculate_pulse_data_value(u32 pulse_count, float coefficient, float offset);

/**
 * @brief 根据配置计算脉冲数据值
 * @details 根据脉冲数据点配置计算脉冲数据值。
 *          使用配置中的系数和偏移进行计算。
 * 
 * @param pulse_count 脉冲计数值
 * @param config 脉冲数据点配置，不能为NULL
 * @return 计算后的实际值
 * 
 * @note 使用配置中的系数和偏移进行计算
 * @warning 配置指针不能为NULL
 * 
 * @see calculate_pulse_data_value
 * @see validate_pulse_point_config
 */
float calculate_pulse_data_from_config(u32 pulse_count, const pulse_point_config_t* config);

/* ==================== 验证辅助函数 ==================== */

/**
 * @brief 验证脉冲点号
 * @details 验证脉冲点号是否在有效范围内。
 *          点号范围：1-65535
 * 
 * @param point_id 脉冲点号
 * @return 验证结果
 *         - 1: 点号有效
 *         - 0: 点号无效
 * 
 * @note 点号范围：1-65535
 * @warning 点号不能为0
 * 
 * @see is_pulse_coefficient_valid
 * @see is_pulse_offset_valid
 */
int is_pulse_point_id_valid(u16 point_id);

/**
 * @brief 验证脉冲系数
 * @details 验证脉冲系数是否在有效范围内。
 *          系数范围：-1000.0 到 1000.0
 * 
 * @param coefficient 脉冲系数
 * @return 验证结果
 *         - 1: 系数有效
 *         - 0: 系数无效
 * 
 * @note 系数范围：-1000.0 到 1000.0
 * @warning 系数不能为NaN或无穷大
 * 
 * @see is_pulse_point_id_valid
 * @see is_pulse_offset_valid
 */
int is_pulse_coefficient_valid(float coefficient);

/**
 * @brief 验证脉冲偏移
 * @details 验证脉冲偏移是否在有效范围内。
 *          偏移范围：-10000.0 到 10000.0
 * 
 * @param offset 脉冲偏移
 * @return 验证结果
 *         - 1: 偏移有效
 *         - 0: 偏移无效
 * 
 * @note 偏移范围：-10000.0 到 10000.0
 * @warning 偏移不能为NaN或无穷大
 * 
 * @see is_pulse_point_id_valid
 * @see is_pulse_coefficient_valid
 */
int is_pulse_offset_valid(float offset);

/**
 * @brief 验证脉冲计数值
 * @details 验证脉冲计数值是否在有效范围内。
 *          计数值范围：0-4294967295
 * 
 * @param pulse_count 脉冲计数值
 * @return 验证结果
 *         - 1: 计数值有效
 *         - 0: 计数值无效
 * 
 * @note 计数值范围：0-4294967295
 * @warning 计数值不能为负数
 * 
 * @see is_pulse_calculated_value_valid
 * @see is_pulse_point_id_valid
 */
int is_pulse_count_valid(u32 pulse_count);

/**
 * @brief 验证脉冲计算值
 * @details 验证脉冲计算值是否在有效范围内。
 *          计算值范围：-1000000.0 到 1000000.0
 * 
 * @param calculated_value 脉冲计算值
 * @return 验证结果
 *         - 1: 计算值有效
 *         - 0: 计算值无效
 * 
 * @note 计算值范围：-1000000.0 到 1000000.0
 * @warning 计算值不能为NaN或无穷大
 * 
 * @see is_pulse_count_valid
 * @see is_pulse_point_id_valid
 */
int is_pulse_calculated_value_valid(float calculated_value);

/**
 * @brief 验证脉冲数据组计数
 * @details 验证脉冲数据组计数是否在有效范围内。
 *          计数范围：1-1000
 * 
 * @param count 脉冲数据组计数
 * @return 验证结果
 *         - 1: 计数有效
 *         - 0: 计数无效
 * 
 * @note 计数范围：1-1000
 * @warning 计数不能为0或过大
 * 
 * @see validate_pulse_data_group
 * @see is_pulse_point_id_valid
 */
int is_pulse_group_count_valid(u32 count);

#ifdef __cplusplus
}
#endif

#endif /* PULSE_DATA_H */
